/**
 * Copyright 2021 Huawei Technologies Co., Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "any_value.h"
#include <gtest/gtest.h>

namespace ge {
class AnyValueUt : public testing::Test {};

TEST_F(AnyValueUt, BasicTypesConstructOk) {
  AnyValue v1(10);
  AnyValue v2(true);
  AnyValue v3(false);
  AnyValue v4(100);
  EXPECT_EQ(v1.Get<int>(), 10);
  EXPECT_EQ(v2.Get<bool>(), true);
  EXPECT_EQ(v3.Get<bool>(), false);
  EXPECT_EQ(v4.Get<int>(), 100);
}

TEST_F(AnyValueUt, BasicTypesAssignOk) {
  AnyValue v1(10);
  EXPECT_EQ(v1.Get<int>(), 10);

  v1 = true;
  EXPECT_EQ(v1.Get<bool>(), true);
  v1 = 200;
  EXPECT_EQ(v1.Get<int>(), 200);
  v1 = false;
  EXPECT_EQ(v1.Get<bool>(), false);
}

TEST_F(AnyValueUt, MutableBasicTypeOk) {
  AnyValue v1(10);
  EXPECT_EQ(v1.Get<int>(), 10);
  auto p = v1.MutableGet<int>();
  EXPECT_NE(p, nullptr);
  *p = 20;
  EXPECT_EQ(v1.Get<int>(), 20);
}
namespace {
struct TestStructA {
  int64_t a;
  int64_t b;
  int64_t c;
};
struct TestStructB {
  std::vector<int32_t> vec;
};
}

TEST_F(AnyValueUt, ClassConstruct1Ok) {
  TestStructA a = {0,10,2000};
  TestStructB b;
  b.vec.resize(100);
  for (int32_t i = 0; i < 100; ++i) {
    b.vec[i] = i * 10;
  }
  AnyValue v1(a);
  EXPECT_EQ(v1.Get<TestStructA>().a, 0);
  EXPECT_EQ(v1.Get<TestStructA>().b, 10);
  EXPECT_EQ(v1.Get<TestStructA>().c, 2000);
}

TEST_F(AnyValueUt, ClassConstruct2Ok) {
  TestStructB b;
  b.vec.resize(100);
  for (int32_t i = 0; i < 100; ++i) {
    b.vec[i] = i * 10;
  }
  AnyValue v1(b);
  EXPECT_EQ(v1.Get<TestStructB>().vec.size(), 100);
  EXPECT_EQ(v1.Get<TestStructB>().vec, b.vec);
  EXPECT_NE(&(v1.Get<TestStructB>().vec), &(b.vec));
}

TEST_F(AnyValueUt, ClassMutableOk) {
  TestStructB b;
  b.vec.resize(100);
  for (int32_t i = 0; i < 100; ++i) {
    b.vec[i] = i * 10;
  }
  AnyValue v1(b);
  auto p = v1.MutableGet<TestStructB>();
  EXPECT_NE(p, nullptr);
  EXPECT_EQ(p->vec, b.vec);
  p->vec[20] = 1024;
  EXPECT_NE(v1.Get<TestStructB>().vec, b.vec);

  b.vec[20] = 1024;
  EXPECT_EQ(v1.Get<TestStructB>().vec, b.vec);
}

TEST_F(AnyValueUt, vector) {
  AnyValue v1(std::vector<int64_t>({1,1,1,1}));
  EXPECT_EQ(*(v1.MutableGet<std::vector<int64_t>>()), std::vector<int64_t>({1,1,1,1}));

  AnyValue v2 = std::move(v1);
  EXPECT_EQ(*(v2.MutableGet<std::vector<int64_t>>()), std::vector<int64_t>({1,1,1,1}));
}

TEST_F(AnyValueUt, charp) {
  AnyValue v1("abc");
  EXPECT_EQ(*(v1.MutableGet<std::string>()), std::string("abc"));

  v1 = "cde";
  EXPECT_EQ(*(v1.MutableGet<std::string>()), std::string("cde"));
}
}  // namespace ge